// 实现symbol
// 实现模版字符串

// iterator
// iterator 使 {} 可迭代 实现for of
// defineProperty 获取私有属性
// proxy 代理实现add[1][2][3] + 1 = 


var mySymbol = (() => {
    const map = new Map();
    function fn() {
        if (this instanceof fn) {
            return new Error('err')
        }
    }

    fn.for = function (key) {
        if (!map.has(key)) {
            map.set(key, {})
        }
        return map.get(key)
    }

    fn.forOf = function (val) {
        for (let [k, v] of map) {
            if (v === val) {
                return k
            }
        }
    }
    return fn
})()

//https://blog.csdn.net/qq_50541792/article/details/127262877
function template(str, obj) {
    for (var key in obj) {
        var reg = new RegExp("{{" + key + "}}")
        str = str.replace(reg, obj[key])
    }
    return str
}

var str = 'I name is {{name}},I from {{from}}'
var obj = {
  from: 'beijing',
  name: 'Tom',
}




// 使等式成立 对象结构变数组
Object.prototype[Symbol.iterator] = function () {
    return Object.values(this)[Symbol.iterator]()
}
var [a, b] = { a: 1, b: 2 }
console.log(a, b)


// 对象可迭代
const myIterator = {
    data: [1, 2, 3, 4],
    [Symbol.iterator]() {
        let index = 0;
        return {
            next: () => {
                return {
                    value: this.data[index++],
                    done: index >= this.data.length
                }
            }
        }
    }
}

for (let val of myIterator) {
    console.log(val, "??")
}
console.log([...myIterator])


// 如何不改原代码的情况下，改obj（私有）
var o = (function(){
    var obj = {
        a: 1,
        b: 2
    }
    return {
        get: function(k){
            return obj[k]
        }
    }
})()

Object.defineProperty(Object.prototype, 'abc', {
    get(){
        return this
    }
})

var obj2 = o.get('abc')
obj2.c=2
obj2.a = "wwww"


// 实现add[2][3][10] + 100
const add = function createProxy(values) {
    return new Proxy(
        {},
        {
            get(target, p, reciver) {
                // 处理很后面正常的加👌
                if (p === Symbol.toPrimitive) { // 知名符号
                    return () => {
                        return values.reduce((a, b) => a + b, 0)
                    }
                }
                return createProxy([...values, +p])
            }
        }
    )
}

// proxy 与defindProperty 的基本范式
Object.defineProperties(data, "name", {
    set(val) {
        // 触发操作
        input.value = val
    },
    get() {}
})

let proxy = new Proxy(data, {
    set(target, key, val) {
        input.value = val;
        return Reflect.set(target, key, val) // 注意// 注意
    },
    get() { }
})


// class 转 es5
// 1. 严格模式 2. 不能直接调用 3. 挂载方法不能枚举 4. 挂载方法不能直接new
'use strict'


function Example(name){
    if(!new.target){ // 不能直接调用
        throw new TypeError('type error')
    }
    this.name = name
}

// Example.prototype.func = fucntion() {
//     console.log(this.name);
// }
Object.defineProperty(Example.prototype, 'func', {
    value: function(){
        if(!new.target){ // 不能直接调用
            throw new TypeError('type error')
        }
        console.log(this.name)
    },
    enumerable: false
})

// Example() 不可以
// new Example.prototype.func()
// const = new Example()